package com.ys.utils.redis;

import com.ys.utils.base.j2se.StringHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Description
 * Created by 王伟
 * Date create on 17:24 2019/11/13.
 */
@Configuration
public class Redis {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public static Key key;
    public static Str str;
    public static List list;
    public static Hash hash;
    public static ZSet zSet;
    public static Set_ set;

    @PostConstruct
    private void init() {
        key = new Key(stringRedisTemplate);
        str = new Str(stringRedisTemplate);
        list = new List(stringRedisTemplate);
        hash = new Hash(stringRedisTemplate);
        zSet = new ZSet(stringRedisTemplate);
        set = new Set_(stringRedisTemplate);
    }


    /**
     * Description 用于操作Redis 的 Key
     * Created by 王伟
     * Date create on 17:24 2019/12/8.
     */
    public class Key {
        private StringRedisTemplate redis;

        Key(StringRedisTemplate redis) {
            this.redis = redis;
        }

        public Long getExpire(String k) {
            return redis.getExpire(k);
        }

        public void del(String k) {
            redis.delete(k);
        }

        public boolean exists(String k) {
            return redis.hasKey(k);
        }

        public boolean setKeyTimeout(String key, Long i) {
            return redis.expire(key, i, TimeUnit.SECONDS);
        }

        public Long increment(String k) {
            return redis.opsForValue().increment(k);
        }

        public Long increment(String k, long v) {
            return redis.opsForValue().increment(k, v);
        }

        public Set<String> keys(String k){return redis.keys(k);}
    }

    /**
     * Description 用于操作Redis 的 Str
     * Created by 王伟
     * Date create on 17:24 2019/12/8.
     */
    public class Str {
        private StringRedisTemplate redis;

        Str(StringRedisTemplate redis) {
            this.redis = redis;
        }

        public void set(String k, Object v, int timeOut) {
            redis.opsForValue().set(k, StringHandler.getString(v), timeOut, TimeUnit.SECONDS);
        }

        public void set(String k, String v) {
            redis.opsForValue().set(k, v);
        }

        public String get(String k) {
            return redis.opsForValue().get(k);
        }

        public String getAndSet(String k, Object v, int timeOut) {
            redis.expire(k, timeOut, TimeUnit.SECONDS);
            return redis.opsForValue().getAndSet(k, StringHandler.getString(v));
        }

        public String getAndExpire(String k, int timeOut) {
            redis.expire(k, timeOut, TimeUnit.SECONDS);
            return redis.opsForValue().get(k);
        }

        public boolean setNX(String key) {
            Boolean boo = redis.opsForValue().setIfAbsent(key, "lock", 10, TimeUnit.SECONDS);
            return boo != null && boo;
        }

        public Long incr(String key){
            return redis.opsForValue().increment(key);
        }

        public Long incr(String key, long value){
            return redis.opsForValue().increment(key,value);
        }
    }

    /**
     * Description 用于操作Redis 的 List
     * Created by 王伟
     * Date create on 17:24 2019/12/8.
     */
    public class List {
        private StringRedisTemplate redis;

        List(StringRedisTemplate redis) {
            this.redis = redis;
        }

        public Long rPush(String key, String value) {
            return redis.opsForList().rightPush(key, value);
        }

        public String rightPop(String k, int timeOut) {
            if (timeOut == 0) {
                return redis.opsForList().rightPop(k);
            }
            return redis.opsForList().rightPop(k, timeOut, TimeUnit.SECONDS);
        }

        public Long lpush(String k, String v) {
            return redis.opsForList().leftPush(k, v);
        }

        public java.util.List<String> range(String key, Long start, Long end) {
            java.util.List<String> range = redis.opsForList().range(key, start, end);
            return range;
        }

        /**
         * 批量添加
         *
         * @param key
         * @param list
         */
        public Long pushList(String key, java.util.List<String> list) {
            return redis.opsForList().leftPushAll(key, list);
        }

        public String lPop(String k){
            return redis.opsForList().leftPop(k);
        }

        /**
         * 获取list长度
         * @param key
         * @return
         */
        public Long size(String key){
            return redis.opsForList().size(key);
        }
    }

    /**
     * Description 用于操作Redis 的 Hash
     * Created by 王伟
     * Date create on 17:24 2019/12/8.
     */
    public class Hash {
        private StringRedisTemplate redis;

        Hash(StringRedisTemplate redis) {

            this.redis = redis;
        }

        /**
         * @param k       key
         * @param hash    hash对象
         * @param timeOut 超时时间
         */
        public void hmset(String k, final Map<String, String> hash, int timeOut) {
            redis.opsForHash().putAll(k, hash);
            redis.expire(k, timeOut, TimeUnit.SECONDS);
        }

        /**
         * @param k    key
         * @param hash hash对象
         */
        public void hmset(String k, final Map<String, String> hash) {
            redis.opsForHash().putAll(k, hash);
        }

        /**
         * @param k      key
         * @param fields field1 field2 ...
         */
        public java.util.List<Object> hmget(String k, java.util.List<Object> fields) {
            return redis.opsForHash().multiGet(k, fields);
        }

        /**
         * @param key   key
         * @param field 字段
         * @param value 值
         */
        public void hSet(String key, String field, String value) {
            redis.opsForHash().put(key, field, value);
        }

        public void hSet(String key, String field, String value, long timeOut) {
            redis.opsForHash().put(key, field, value);
            redis.expire(key, timeOut, TimeUnit.SECONDS);
        }
        /**
         * 获得 hash 中某个key
         *
         * @param key
         * @param field
         * @return
         */
        public Object hGet(String key, String field) {
            return redis.opsForHash().get(key, field);
        }

        public Map<Object, Object> hgetall(String k) {
            return redis.opsForHash().entries(k);
        }

        public Long hincrBy(String k, String hash, long v, int timeOut) {
            Long num = redis.opsForHash().increment(k, hash, v);
            redis.expire(k, timeOut, TimeUnit.SECONDS);
            return num;
        }

        /**
         * 删除 hash 中某个 hashKey
         *
         * @param key   key
         * @param field hashKey
         * @return
         */
        public Long delHash(String key, Object... field) {
            return redis.opsForHash().delete(key, field);
        }

        /**
         * 判断 hash 中是否存在值
         *
         * @param key   key
         * @param field 字段名称
         * @return
         */
        public boolean hasValue(String key, String field) {
            return redis.opsForHash().hasKey(key, field);
        }

    }

    public class ZSet {
        private StringRedisTemplate redis;

        ZSet(StringRedisTemplate redis) {
            this.redis = redis;
        }

        public Long zremrangebyrank(String key,long start,long stop){
            return redis.opsForZSet().removeRange(key,start,stop);
        }
        public boolean add(String key, String value, Integer score) {
            return redis.opsForZSet().add(key, value, score);
        }

        /**
         * 添加成员
         *
         * @param key
         * @param tuples
         * @return
         */
        public Long add(String key, Set<ZSetOperations.TypedTuple<String>> tuples) {
            return redis.opsForZSet().add(key, tuples);
        }

        /**
         * 判断value在zset中的排名  zrank
         *
         * @param key
         * @param value
         * @return
         */
        public Long rank(String key, String value) {
            return redis.opsForZSet().rank(key, value);
        }

        public Double score(String key, Object value) {
            return redis.opsForZSet().score(key, value);
        }


        /**
         * 移除成员
         *
         * @param key
         * @param value
         */
        public void remove(String key, String value) {
            redis.opsForZSet().remove(key, value);
        }

        /**
         * 返回集合的长度
         *
         * @param key
         * @return
         */
        public Long size(String key) {
            return redis.opsForZSet().zCard(key);
        }

        /**
         * 查询集合中指定顺序的值， 0 -1 表示获取全部的集合内容  zrange
         * <p>
         * 返回有序的集合，score小的在前面
         *
         * @param key
         * @param start
         * @param end
         * @return
         */
        public Set<String> range(String key, int start, int end) {
            return redis.opsForZSet().range(key, start, end);
        }

        /**
         * 查询集合中指定顺序的值  zrevrange
         * <p>
         * 返回有序的集合中，score大的在前面
         *
         * @param key
         * @param start
         * @param end
         * @return
         */
        public Set<String> revRange(String key, int start, int end) {
            return redis.opsForZSet().reverseRange(key, start, end);
        }

        /**
         * 获取指定区间的成员信息
         *
         * @param key key
         * @param min 最小
         * @param max 最大
         * @return
         */
        public Set<String> rangeByScore(String key, Double min, Double max) {
            return redis.opsForZSet().rangeByScore(key, min, max);
        }
    }

    public class Set_ {
        private StringRedisTemplate redis;

        Set_(StringRedisTemplate redis) {
            this.redis = redis;
        }

        /**
         * 添加成员
         *
         * @param key
         * @param values
         * @return
         */
        public Long add(String key, String... values) {
            return redis.opsForSet().add(key,values);
        }

        /**
         * 随机获取元素
         *
         * @param key
         * @return
         */
        public String sRandMember(String key) {
            return redis.opsForSet().randomMember(key);
        }
    }
}
